
import yaml, requests, json, datetime, os
from urllib.parse import quote
from typing import List

class Prom2Qywx:
    def __init__(self, cfg_path="daily.yaml"):
        with open(cfg_path, encoding="utf-8") as f:
            self.cfg = yaml.safe_load(f)
        self.ps = self.cfg["prometheus"]["base_url"]
        self.qywx_url = self.cfg["qywx"]["webhook"]
        self.mentioned = self.cfg["qywx"]["mentioned"]

    # ---------- 查 Prometheus ----------
    def query(self, promql: str):
        """返回 list[dict], 每个 dict 包含 metric 和 value/values"""
        url = f"{self.ps}/api/v1/query"
        params = {"query": promql, "time": int(datetime.datetime.now().timestamp())}
        resp = requests.get(url, params=params, timeout=15)
        resp.raise_for_status()
        data = resp.json()
        if data["status"] != "success":
            raise RuntimeError("Prometheus 查询失败: " + str(data))
        return data["data"]["result"]

    # ---------- 格式化 ----------
    @staticmethod
    def format_result(name, unit,result,threshold):
        lines = [f"【{name}】"]
        if not result:
            lines.append("  无数据")
            return " ".join(lines)
        for vec in result:
            labels = ",".join(f"{k}={v}" for k, v in vec["metric"].items())
            val = vec["value"][1]
            # 如果采集指标超过阈值,就加入到推送信息中.
            if float(val) > threshold:
                lines.append(f"  {labels}  {float(val):.2f} {unit}")
        return "\n".join(lines)

    # ---------- 发企微 ----------
    # 这个是为了解决消息体过大.需要分消息发送.
    # text类型消息,消息体限制 2048 
    # Markdown类型,限制 4096
    def send_qywx(self,lines: List[str],max_bytes: int = 3800):
        buf ,buf_len,size =[],0,1
        for line in lines:
            line_len = len(line.encode()) + 1
            if  buf_len + line_len > max_bytes:
                self.send_qywx_msg("\n".join(buf))
                size = size+1
                buf, buf_len = [], 0
            buf.append(line)
            buf_len += line_len
        if buf:
            self.send_qywx_msg("\n".join(buf)+ f"\n 一共 {size} 条消息")

    def send_qywx_msg(self, content: str):
        payload = {
            "msgtype": "markdown",
            "markdown": {"content": content}
        }
        r = requests.post(self.qywx_url, json=payload, timeout=10)
        r.raise_for_status()

    # ---------- 一键运行 ----------
    def run(self):
        blocks = []
        for q in self.cfg["daily"]:
            try:
                data = self.query(q["promql"])
                blocks.append(self.format_result(q["name"], q["unit"],data,q["threshold"]))
            except Exception as e:
                blocks.append(f"【{q['name']}】查询失败：{e}")
        # self.send_qywx(blocks)
        print("\n".join(blocks))
        print("消息已推送")


if __name__ == "__main__":
    Prom2Qywx().run()